home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource for Source: C/C++
/
Resource for Source - C-C++.iso
/
misc_src
/
cslib16b
/
csdbgen
/
demo.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-01
|
19KB
|
609 lines
/////////////////////////////////////////////////////////
// Implementation file of database class: NAC.
//
// Source generated by: CSDBGEN version 1.2.b.
// Date of generation: Thursday, 2 March 1995.
// Time of generation: 12:02:10.
//
//
// The next lines represent the database definition
// file used as input for CSDBGEN.
//
//
////////////// Start of the .def file //////////////////
/*
class: NAC
record: nac_record
file: dbfile
field: name s 40 T
field: address s 30 Y
field: city s 20 Y
field: birthday d Y4MD Y
field: salary f
*/
/////////////// End of .def file //////////////////////////////////////////////
/*
█████ █ █
██ ██ ██ ██
███ ████ ███ ██ ███ ████
███ ██ ██ ███ ██ ██
███ ██ █████ ██ ██
██ ██ ██ █ ██ ██ ██ ██ █
█████ ██ ███ ██ ██ ██
████ ████ ██ ██ ██ ███ █████ ████
██ ██ ██ ██ ██ ███ ██ ██ █ ██ ██
████ ██ ██ ██ ██ ██ ██ ██████
██ ██ ██ ██ ██ ██ ██ █ ██
████ ████ ███ ██ ██ █████ █████
*/
//////////////////////////////////////////////////////////////////////////////
#include "demo.h"
extern unsigned _stklen=7000; //A large stack is needed
///////////////////////////////// Constructor ////////////////////////////////
NAC::NAC(void)
{
is_open=FALSE;
current=1;
_birthday.format(Y4MD);
}
///////////////////////////////// reindex ////////////////////////////////////
void NAC::reindex(void)
{
U32 l=current;
nac_record *rp;
in1.empty();
in2.empty();
in3.empty();
in4.empty();
for(current=numrec(); current>0; current--)
{
rp=(nac_record *)db.locate_rec(current);
tokenize(rp->_name,&NAC::in1_ins_tok);
in2.insert(rp->_address,¤t);
in3.insert(rp->_city,¤t);
in4.insert(&rp->__birthday,¤t);
}
current=l;
}
/////////////// go_to ////////////////////////////////////////////
void NAC::go_to(long n)
{
if(order()!=UNSORTED)
{
csmess_p(7110,"NAC");
return;
}
write_rec();
current=max(min(n,db.numrec()),1);
read_rec();
}
/////////////// append blank//////////////////////////////////////
void NAC::append_blank(void)
{
append();
tokenize(recp->_name,&NAC::in1_ins_tok);
in2.insert(rec._address,¤t);
in3.insert(rec._city,¤t);
in4.insert(&rec.__birthday,¤t);
}
///////////////////////////////// append /////////////////////////////////////
// This function doesn't update the indexes, which can save some
// disk I/O because you are likely to alter the fields
// immediately after you have appended the record.
// However, if you have an index on a field you don't update, this
// record will NOT appear in that particular index!
// The 'append_blank' function does update all indexes, which
// makes it a safer, but slower option.
//
void NAC::append(void)
{
write_rec();
memset(&rec,0,sizeof(nac_record));
current=db.append_rec(&rec);
recp=(nac_record *)db.locate_rec(current);
dirty=TRUE;
_birthday.sem_jul(0L);
}
///////////////////////////////// open ///////////////////////////////////////
void NAC::open(void)
{
if(is_open) return;
int needs_reindex=FALSE;
dirty=FALSE;
#ifdef _Windows
int fre=300/9; //Use 300 Kb for buffers. You may increase this.
#else
int fre=(int)(coreleft()-100000L)/9/1024;
fre=max(fre,0);
#endif
if(!db.open("dbfile.dbf",fre))
{
csmess_disp("FATAL: Can't open database dbfile.dbf.");
exit(1);
}
if(db.lengthrec()!=sizeof(nac_record))
{
csmess_disp("FATAL: wrong record size.\n\rProbably wrong or old database file.");
db.close();
exit(1);
}
if(!file_exist("dbfile01.idx"))
{
in1.multiple_keys(TRUE);
in1.define("dbfile01.idx",NAME_LENGTH/2,sizeof(long));
needs_reindex=TRUE;
}
in1.open("dbfile01.idx",fre*2);
if(!file_exist("dbfile02.idx"))
{
in2.multiple_keys(TRUE);
in2.define("dbfile02.idx",ADDRESS_LENGTH+1,sizeof(long));
needs_reindex=TRUE;
}
in2.open("dbfile02.idx",fre*2);
if(!file_exist("dbfile03.idx"))
{
in3.multiple_keys(TRUE);
in3.define("dbfile03.idx",CITY_LENGTH+1,sizeof(long));
needs_reindex=TRUE;
}
in3.open("dbfile03.idx",fre*2);
if(!file_exist("dbfile04.idx"))
{
in4.multiple_keys(TRUE);
in4.define("dbfile04.idx",sizeof(long),sizeof(long));
needs_reindex=TRUE;
}
in4.open("dbfile04.idx",fre*2);
if(needs_reindex) reindex();
is_open=TRUE;
if(numrec()==0) append_blank();
else read_rec();
order(UNSORTED);
}
///////////////////////////////// close //////////////////////////////////////
void NAC::close(void)
{
if(!is_open) return;
write_rec();
db.close();
in1.close();
in2.close();
in3.close();
in4.close();
is_open=FALSE;
}
///////////////////////////////// define /////////////////////////////////////
void NAC::define(void)
{
db.define("dbfile.dbf",sizeof(nac_record));
in1.multiple_keys(TRUE);
in1.define("dbfile01.idx",NAME_LENGTH/2,sizeof(long));
in2.multiple_keys(TRUE);
in2.define("dbfile02.idx",ADDRESS_LENGTH+1,sizeof(long));
in3.multiple_keys(TRUE);
in3.define("dbfile03.idx",CITY_LENGTH+1,sizeof(long));
in4.multiple_keys(TRUE);
in4.define("dbfile04.idx",sizeof(long),sizeof(long));
}
///////////////////////////////// pack ///////////////////////////////////////
void NAC::pack(void)
{
write_rec();
db.pack();
reindex();
if(numrec()==0) append_blank();
top();
}
///////////////////////////////// skip ///////////////////////////////////////
int NAC::skip0(int delta)
{
long old_current=current;
current=max(min(current+delta,db.numrec()),1);
return current-old_current;
}
int NAC::skip(int delta)
{
int rc;
write_rec();
rc=(this->*skip_fun)(delta);
read_rec();
return rc;
}
///////////////////////////////// order //////////////////////////////////////
void NAC::order(int nr)
{
switch(nr)
{
case 0: //Unsorted
bof_fun =&NAC::bof0;
eof_fun =&NAC::eof0;
skip_fun =&NAC::skip0;
top_fun =&NAC::top0;
bottom_fun=&NAC::bottom0;
search_fun=&NAC::search0;
break;
case 1: //Index on field name
bof_fun =&NAC::bof1;
eof_fun =&NAC::eof1;
skip_fun =&NAC::skip1;
top_fun =&NAC::top1;
bottom_fun=&NAC::bottom1;
search_fun=&NAC::search1;
break;
case 2: //Index on field address
bof_fun =&NAC::bof2;
eof_fun =&NAC::eof2;
skip_fun =&NAC::skip2;
top_fun =&NAC::top2;
bottom_fun=&NAC::bottom2;
search_fun=&NAC::search2;
break;
case 3: //Index on field city
bof_fun =&NAC::bof3;
eof_fun =&NAC::eof3;
skip_fun =&NAC::skip3;
top_fun =&NAC::top3;
bottom_fun=&NAC::bottom3;
search_fun=&NAC::search3;
break;
case 4: //Index on field birthday
bof_fun =&NAC::bof4;
eof_fun =&NAC::eof4;
skip_fun =&NAC::skip4;
top_fun =&NAC::top4;
bottom_fun=&NAC::bottom4;
search_fun=&NAC::search4;
break;
default: return; // Function called with wrong parameter.
}
iOrder=nr;
top();
}
/////////////////////////////writing record ///////////////////////////////
void NAC::write_rec2(void)
{
if(strcmp(recp->_name,rec._name))
{
tokenize(recp->_name,&NAC::in1_del_tok);
tokenize(rec._name,&NAC::in1_ins_tok);
}
if(strcmp(recp->_address,rec._address))
{
in2.delet(recp->_address,¤t);
in2.insert(rec._address,¤t);
}
if(strcmp(recp->_city,rec._city))
{
in3.delet(recp->_city,¤t);
in3.insert(rec._city,¤t);
}
rec.__birthday=_birthday.sem_jul();
if(recp->__birthday!=rec.__birthday)
{
in4.delet(&recp->__birthday,¤t);
in4.insert(&rec.__birthday,¤t);
}
db.write_rec(current,&rec);
dirty=FALSE;
}
///////////////////////////////// export /////////////////////////////////////
int NAC::export(char *s)
{
FILE *fo=fopen(s,"w");
if(fo==NULL) return FALSE;
write_rec();
fprintf(fo,"class: NAC");
fprintf(fo,"\nrecord: nac_record");
fprintf(fo,"\nfile: dbfile");
fprintf(fo,"\nfield: name s 40 Y");
fprintf(fo,"\nfield: address s 30 Y");
fprintf(fo,"\nfield: city s 20 Y");
fprintf(fo,"\nfield: birthday d Y");
fprintf(fo,"\nfield: salary f ");
if(ferror(fo)) { fclose(fo); return FALSE; }
nac_record *recp;
DATE conv;
conv.format(Y4MD);
for(long l=numrec();l>0;l--)
{
recp=( nac_record * )db.locate_rec(l);
fprintf(fo,"\n%c",12);
fprintf(fo,"\n%s",recp->_name);
fprintf(fo,"\n%s",recp->_address);
fprintf(fo,"\n%s",recp->_city);
conv.sem_jul(recp->__birthday);
fprintf(fo,"\n%s",(char *)conv);
fprintf(fo,"\n%g",recp->_salary);
fprintf(fo,"\n"); //Additional linefeed, to avoid trouble!
if(ferror(fo)) { fclose(fo); return FALSE; }
}
return !fclose(fo);
}
///////////////////////////////// import /////////////////////////////////////
int NAC::import(char *s)
{
FILE *fr=fopen(s,"r");
if(fr==NULL) return FALSE;
#define MAX_NUM_FIELDS 100 //Increase this to allow more fields
#define MAX_FIELD_LEN 500 //Increase this to allow longer fields
int *finu;
finu=(int *)malloc(MAX_NUM_FIELDS*sizeof(int));
if(finu==NULL) { fclose(fr); return FALSE; }
char *fibu;
fibu=(char *)malloc(MAX_FIELD_LEN);
if(fibu==NULL) { fclose(fr); free(finu); return FALSE; }
*fibu=0;
char *fipo=fibu+strlen("field:");
char *cp;
int ifieldnr=0;
int ofieldnr;
DATE conv;
conv.format(Y4MD);
memset(finu,0,MAX_NUM_FIELDS*sizeof(int));
fgets(fibu,MAX_FIELD_LEN,fr);
while(!strchr(fibu,12))
{
strlwr(fibu);
notabs(fibu);
trim_string(fibu);
if(strstr(fibu,"field:"))
{
ifieldnr++;
trim_string(fipo);
if((cp=strchr(fipo,' '))!=NULL) *cp=0;
if (!strcmp(fipo,"name")) ofieldnr=1;
else if(!strcmp(fipo,"address")) ofieldnr=2;
else if(!strcmp(fipo,"city")) ofieldnr=3;
else if(!strcmp(fipo,"birthday")) ofieldnr=4;
else if(!strcmp(fipo,"salary")) ofieldnr=5;
else ofieldnr=0;
finu[ifieldnr]=ofieldnr;
}
fgets(fibu,MAX_FIELD_LEN,fr);
}
for(;;)
{
if(!strchr(fibu,12))
{
ifieldnr++;
if(ifieldnr<MAX_NUM_FIELDS)
switch(finu[ifieldnr])
{
case 0: break;
case 1:
fibu[NAME_LENGTH]=0;
name(fibu);
break;
case 2:
fibu[ADDRESS_LENGTH]=0;
address(fibu);
break;
case 3:
fibu[CITY_LENGTH]=0;
city(fibu);
break;
case 4:
conv=fibu;
_birthday.sem_jul(conv.sem_jul());
break;
case 5:
salary(atof(fibu));
break;
}
}
else
{
ifieldnr=0;
append_blank();
}
if(feof(fr)) break;
fgets(fibu,MAX_FIELD_LEN,fr);
cp=fibu+(max(1,strlen(fibu))-1);
if(*cp=='\n') *cp=0; //removing the line feed
}
fclose(fr);
free(fibu);
free(finu);
#undef MAX_NUM_FIELDS
#undef MAX_FIELD_LEN
return TRUE;
}
///////////////////////////////// export to dBASE compatible file. ///////////
int NAC::to_DBASE(char *s)
{
char bufje[12];
if(!is_open) return FALSE;
write_rec();
FILE *fo=fopen(s,"wb");
if(fo==NULL) return FALSE;
int i;
DATE d_upda;
d_upda.sem_jul(db.sj_updated());
fputc(03,fo);
fputc(d_upda.year()%100,fo);
fputc(d_upda.month(),fo);
fputc(d_upda.day(),fo);
long nr_record=numrec();
fwrite(&nr_record,sizeof(long),1,fo);
putw(194,fo); //Header length
putw(113,fo); //Length of data record
for(i=0;i<20;i++) fputc(0,fo); // 20 dummy bytes
// Writing definition of field name to dbase file header.
memset(bufje,0,11);
strcpy(bufje,"NAME");
fwrite(bufje,11,1,fo);
fputc('C',fo);
for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
fputc(40,fo);
fputc(0,fo);
for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
// Writing definition of field address to dbase file header.
memset(bufje,0,11);
strcpy(bufje,"ADDRESS");
fwrite(bufje,11,1,fo);
fputc('C',fo);
for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
fputc(30,fo);
fputc(0,fo);
for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
// Writing definition of field city to dbase file header.
memset(bufje,0,11);
strcpy(bufje,"CITY");
fwrite(bufje,11,1,fo);
fputc('C',fo);
for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
fputc(20,fo);
fputc(0,fo);
for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
// Writing definition of field birthday to dbase file header.
memset(bufje,0,11);
strcpy(bufje,"BIRTHDAY");
fwrite(bufje,11,1,fo);
fputc('D',fo);
for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
fputc(8,fo);
fputc(0,fo);
for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
// Writing definition of field salary to dbase file header.
memset(bufje,0,11);
strcpy(bufje,"SALARY");
fwrite(bufje,11,1,fo);
fputc('N',fo);
for(i=0;i<4;i++) fputc(0,fo); // 4 dummy bytes
fputc(14,fo);
fputc(7,fo);
for(i=0;i<14;i++) fputc(0,fo); // 14 dummy bytes
fputc(13,fo); //Field terminator
fputc(0,fo);
// By now we have written the definition of the
// record structure to the file header.
// From here on we will export the records.
nac_record *recp;
for(long l=numrec();l>0;l--)
{
if(ferror(fo)) { fclose(fo); return FALSE; }
recp=(nac_record *)db.locate_rec(l);
if(db.is_delet(l)) fputc(42,fo);
else fputc(32,fo);
/////////////////////// writing field name /////////////
fprintf(fo,"%-40s",recp->_name);
/////////////////////// writing field address /////////////
fprintf(fo,"%-30s",recp->_address);
/////////////////////// writing field city /////////////
fprintf(fo,"%-20s",recp->_city);
/////////////////////// writing field birthday /////////////
if(recp->__birthday)
{
d_upda.sem_jul(recp->__birthday);
fprintf(fo,"%4d",d_upda.year4());
fprintf(fo,"%02d",d_upda.month());
fprintf(fo,"%02d",d_upda.day());
}
else
{
fprintf(fo," ");
}
/////////////////////// writing field salary /////////////
fprintf(fo,"%14.7f",recp->_salary);
}
fputc(26,fo); //End of File
fclose(fo);
return TRUE;
}
///////////////////////////////// tokenize field ///////////////////////
void NAC::tokenize(char *s,void(NAC::*fun)(void *))
{
char delim[]="\t,()- "; //Token delimiters
const min_len=4; //Minimum length for a token to be indexed.
char *p,*q=s;
char c;
int insert=FALSE;
p=strpbrk(q,delim);
while(p)
{
c=*p; *p=0;
if(strlen(q)>=min_len) { (this->*fun)(q); insert=TRUE; }
*p=c;
do{ p=strpbrk(q=p+1,delim); }while(q==p);
}
if(strlen(q)>=min_len) { (this->*fun)(q); insert=TRUE; }
if(!insert) (this->*fun)(s);
}